﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreApp.DBModel;
using CoreApp.Utility;
using CoreApp.WebApi.Core;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using NLog.Extensions.Logging;
using NLog.Web;
using Swashbuckle.AspNetCore.Swagger;

namespace CoreApp.WebApi
{
    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            //注册数据库连接串配置实例
            services.Configure<DBConnectionConfig>(Configuration.GetSection("DBConnection"));

            #region 依赖注入
            //（单独依赖注入）ASP.net Core自带的注入方式
            //services.AddScoped<IUserRepository,UserRepository>();//如果依赖注入很多，这种单独注入的方式维护很麻烦。

            /*
             * 批量依赖注入服务(也可以用第三方IOC框架实现批量注入，如：Autofac)
             * 这里注入CoreApp.DapperAccess程序集下的类名后缀为Repository的服务（所以需要引用CoreApp.DapperAccess程序集）
             */
            var dicList = CommonUnit.GetClassAndInterfacePairList("CoreApp.DapperAccess", "Repository");
            foreach (var item in dicList)
            {
                foreach (var typeItem in item.Value)
                {
                    services.AddScoped(typeItem, item.Key);
                }
            }
            #endregion

            #region 添加jwt验证
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options => {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,//是否验证Issuer
                    ValidateAudience = true,//是否验证Audience
                    ValidateLifetime = true,//是否验证失效时间
                    ClockSkew = TimeSpan.FromSeconds(15),//校验过期时前后时间偏差容错
                    ValidateIssuerSigningKey = true,//是否验证SecurityKey
                    ValidAudience = Const.Domain,//Audience，需要和前面AuthController中签发jwt的设置一致
                    ValidIssuer = Const.Domain,//Issuer，需要和前面AuthController中签发jwt的设置一致
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Const.SecurityKey))//拿到SecurityKey
                };
                options.Events = new JwtBearerEvents
                {
                    OnAuthenticationFailed = context =>
                    {
                        //Token expired
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            context.Response.Headers.Add("Token-Expired", "true");
                        }
                        return Task.CompletedTask;
                    }
                };
            });
            #endregion

            //注册Swagger
            services.AddSwaggerGen(s =>
            {
                s.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "My Swagger Api",
                    Description = "接口文档"
                }
                );
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                //app.UseHsts();//Hsts(HTTP Strict Transport Security Protocol ) 是一个安全功能，它告诉浏览器只能通过HTTPS访问当前资源，而不是HTTP。
            }

            //app.UseHttpsRedirection();//强制使用https，把所有的HTTP请求转换为HTTPS

            ///添加jwt验证
            app.UseAuthentication();

            //配置NLog
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//这是为了防止中文乱码
            loggerFactory.AddNLog();//添加NLog
            env.ConfigureNLog("nlog.config");//读取Nlog配置文件

            //Swagger
            app.UseSwagger();
            app.UseSwaggerUI(s =>
            {
                s.SwaggerEndpoint("/swagger/v1/swagger.json", "My Swagger Api v1");
                s.RoutePrefix = string.Empty;
            });

            app.UseMvc();
        }
    }
}
